package com.hp.bon.sgw.snmp;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.snmp4j.agent.NotificationOriginator;
import org.snmp4j.agent.mo.MOTable;
import org.snmp4j.agent.mo.MOTableRow;
import org.snmp4j.smi.Counter32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Variable;
import org.snmp4j.smi.VariableBinding;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.hp.bon.sgw.bean.SysParamBean;
import com.hp.bon.sgw.bean.SysPertriNetBean;
import com.hp.bon.sgw.ctrl.ControllerConfigService;
import com.hp.bon.sgw.ctrl.NodeDataFetcher;
import com.hp.bon.sgw.ctrl.SGWAgentInterface;
import com.hp.bon.sgw.ctrl.SGWRemoteInterface;
import com.hp.bon.sgw.domain.CapabilityInfo;
import com.hp.bon.sgw.domain.Node;
import com.hp.bon.sgw.domain.OpenedCapability;
import com.hp.bon.sgw.util.Comutils;
import com.hp.bon.sgw.util.RmiAgentUtil;
import com.hp.ocs.omc.task.rmiagent.bean.ProcessVO;

public class SGWMibSetter {
	private static final Logger logger = LoggerFactory.getLogger(SGWMibSetter.class);
	private SgwMib sgwMib;
	private NotificationOriginator notificationOriginator;
	private NodeDataFetcher nodeDataFetcher;
	private Map<String, SysParamBean> sysparamsMap;
	private Map<Integer, Node> nodeMap = null;
	private List<CapabilityInfo> capabilitys = null;
	private String configFile;
	private SGWRemoteInterface sgwRemoteInterface = null;

	public void init() {
		logger.info("init mibs ...");
		File confFile = new File(this.configFile);
		try {
			this.sysparamsMap = Comutils.loadSysParams(confFile);
			this.sgwRemoteInterface = ControllerConfigService.getInstance().getSgwRemoteServer();

			initSGWInfo();

			initProtocol();
			while (true) {
				this.capabilitys = this.nodeDataFetcher.getCapablityInfos();
				this.nodeMap = this.nodeDataFetcher.getNodeMap();

				initCapability();

				initUser();

				initNodeCapability();

				initSRInfo();
				Thread.sleep(180000L);

				initResource();
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.warn("load SGW Mib error. " + e);
		}
	}

	private void initResource() {
		logger.info("load resource used");
		SGWAgentInterface agent = RmiAgentUtil.getAgentInterface();
		if (agent != null) {
			try {
				String cpuMemVal = agent.getCpuMemPerc();
				Map cpuMem = (Map) new Gson().fromJson(cpuMemVal, new TypeToken() {
				}.getType());
				this.sgwMib.getNeCpuRate().setValue(new OctetString((String) cpuMem.get("cpu")));
				this.sgwMib.getNeMemRate().setValue(new OctetString((String) cpuMem.get("mem")));

				MOTable table = this.sgwMib.getProcResourceUsedEntry();
				clearTable(table);
				MOTableRow row = null;
				int i = 0;

				String mProcessJson = agent.getMProcess();
				Map p = (Map) new Gson().fromJson(mProcessJson, new TypeToken() {
				}.getType());

				Iterator _it = p.keySet().iterator();
				double cpu = 0.0;
				double mem = 0.0;
				while (_it.hasNext()) {
					Long entityNode = (Long) _it.next();
					ProcessVO vo = (ProcessVO) p.get(entityNode);
					if (vo != null)
						if ((vo.getProcessId() == null) || ("".equals(vo.getProcessId()))) {
							logger.warn(vo.getProcessName() + " is not running");
						} else {
							try {
								cpu = Double.valueOf(vo.getCpuPerc()).doubleValue();
							} catch (Exception e) {
								logger.warn("format cpu value error,value:" + vo.getCpuPerc() + "," + e.toString());
								cpu = 0.0D;
							}
							try {
								mem = Double.valueOf(vo.getMemPerc()).doubleValue();
							} catch (Exception e) {
								logger.warn("format mem value error,value:" + vo.getMemPerc() + "," + e.toString());
								mem = 0.0D;
							}

							row = table.createRow(new OID(String.valueOf(i)), new Variable[] { new Counter32(Integer.valueOf(vo.getProcessId()).intValue()), new OctetString(vo.getProcessName()), new OctetString(String.valueOf(cpu)), new OctetString(String.valueOf(mem)) });
							table.addRow(row);
							i++;
						}
				}
			} catch (Exception e) {
				logger.warn("load SGW Resource CPU&MEM error. " + e);
			}
		}

		if (this.sgwRemoteInterface != null) {
			try {
				String useSize = this.sgwRemoteInterface.getQueueSize();

				this.sgwMib.getNeQueRate().setValue(new Counter32(Integer.valueOf(useSize).intValue()));
			} catch (Exception e) {
				logger.warn("load SGW QueueSize error. " + e);
			}
			try {
				String maxSize = this.sgwRemoteInterface.getQueueMaxSize();
				this.sgwMib.getNeQueSize().setValue(new Counter32(Integer.valueOf(maxSize).intValue()));
			} catch (Exception e) {
				logger.warn("load SGW QueueMaxSize error. " + e);
			}
		}
	}

	private void initSGWInfo() {
		this.sgwMib.getNeid().setValue(new Counter32(Integer.valueOf(((SysParamBean) this.sysparamsMap.get("system.ne_type_id")).getValue()).intValue()));
		this.sgwMib.getSgwid().setValue(new Counter32(1L));
		this.sgwMib.getNename().setValue(new OctetString(((SysParamBean) this.sysparamsMap.get("system.sgw_server_name")).getValue()));
		this.sgwMib.getDeployaddr().setValue(new OctetString(((SysParamBean) this.sysparamsMap.get("system.deployaddr")).getValue()));
		this.sgwMib.getNEVendorName().setValue(new OctetString(((SysParamBean) this.sysparamsMap.get("system.vendor")).getValue()));
		this.sgwMib.getNeversion().setValue(new OctetString(((SysParamBean) this.sysparamsMap.get("system.version")).getValue()));
		this.sgwMib.getNodeId().setValue(new OctetString(((SysParamBean) this.sysparamsMap.get("system.dr_id")).getValue()));
		logger.debug("load SGW info done.");
	}

	private void initNodeCapability() {
		List<OpenedCapability> ops = this.nodeDataFetcher.getOpenedCapabilityList();
		MOTable userserTable = this.sgwMib.getUserServInfoEntry();
		clearTable(userserTable);
		MOTableRow row = null;
		int i = 0;
		for (OpenedCapability op : ops) {
			Node u = (Node) this.nodeMap.get(Integer.valueOf(op.getNodeId()));
			if (u != null) {
				row = userserTable.createRow(new OID(String.valueOf(i)), new Variable[] { new Counter32(i), new OctetString(u.getNodeCode()), new OctetString(op.getCapability()) });
				userserTable.addRow(row);
				i++;
			}
		}
		logger.debug("load User Capability done.");
	}

	private void clearTable(MOTable table) {
		int count = table.getModel().getRowCount();
		for (int i = count; i > 0; i--)
			table.removeRow(table.getModel().lastRow().getIndex());
	}

	private void initUser() {
		MOTable userTable = this.sgwMib.getUserInfoEntry();
		clearTable(userTable);
		MOTableRow row = null;
		int i = 0;
		for (Map.Entry u : this.nodeMap.entrySet()) {
			if ((((Node) u.getValue()).getNodeType() >= 5) && (((Node) u.getValue()).getNodeType() <= 8)) {
				row = userTable.createRow(new OID(String.valueOf(i)), new Variable[] { new OctetString(((Node) u.getValue()).getNodeCode()), new OctetString(((Node) u.getValue()).getHostId()), new OctetString(""), new OctetString(((Node) u.getValue()).getNodeDesc()) });
				userTable.addRow(row);
				i++;
			}
		}
		logger.debug("load User info done.");
	}

	private void initCapability() {
		MOTable capabilityTable = this.sgwMib.getServiceInfoEntry();
		clearTable(capabilityTable);
		MOTableRow row = null;
		int i = 0;
		for (CapabilityInfo c : this.capabilitys) {
			row = capabilityTable.createRow(new OID(String.valueOf(i)), new Variable[] { new Counter32(i), new OctetString(c.getCapability()), new OctetString(c.getCapabilityName() == null ? "" : c.getCapabilityName()), new OctetString(c.getCapabilityDesc() == null ? "" : c.getCapabilityDesc()) });
			capabilityTable.addRow(row);
			i++;
		}
		logger.debug("load Capability info done.");
	}

	private void initProtocol() {
		MOTable protocolTable = this.sgwMib.getProtocolInfoEntry();
		clearTable(protocolTable);
		MOTableRow row0 = protocolTable.createRow(new OID("0"), new Variable[] { new Counter32(0L), new OctetString("SOAP"), new OctetString("1.0"), new OctetString("SOAP Protocal"), new Counter32(60L) });
		MOTableRow row1 = protocolTable.createRow(new OID("1"), new Variable[] { new Counter32(1L), new OctetString("SCSP"), new OctetString("1.0"), new OctetString("SCSP Protocol"), new Counter32(60L) });
		MOTableRow row2 = protocolTable.createRow(new OID("2"), new Variable[] { new Counter32(2L), new OctetString("DCC"), new OctetString("1"), new OctetString("Dimeter "), new Counter32(45L) });
		MOTableRow row3 = protocolTable.createRow(new OID("3"), new Variable[] { new Counter32(3L), new OctetString("Tuxedo"), new OctetString("9.1"), new OctetString("Tuxedo Protocol "), new Counter32(30L) });
		protocolTable.addRow(row0);
		protocolTable.addRow(row1);
		protocolTable.addRow(row2);
		protocolTable.addRow(row3);
		logger.debug("load Protocol info done.");
	}

	private void initSRInfo() {
		MOTable srTable = this.sgwMib.getRouteInfoEntry();
		clearTable(srTable);
		MOTableRow row = null;
		int i = 0;
		for (Map.Entry entry : this.nodeMap.entrySet()) {
			if (((Node) entry.getValue()).getNodeType() == 1) {
				row = srTable.createRow(new OID(String.valueOf(i)), new Variable[] { new Counter32(i), new OctetString(((Node) entry.getValue()).getIP()), new Counter32(((Node) entry.getValue()).getPort()), new OctetString(((Node) entry.getValue()).getHostId()),
						new OctetString(((Node) entry.getValue()).getRealm()) });
				srTable.addRow(row);
				i++;
			}
		}
		logger.debug("load RouteInfo done.");
	}

	public void notifySGWStatesChanged(int oldstatus, int newstatus, long time) {
		logger.info("do notifySGWStatesChanged");
		boolean isOnnet = SysPertriNetBean.getIfOnNet(newstatus);
		this.sgwMib.getSgwbsnstate().setValue(new Counter32(isOnnet ? 0 : 1));
		this.sgwMib.getSgwnestate().setValue(new Counter32(SysPertriNetBean.getSNMPStatusCode(newstatus)));
		this.sgwMib.getSgwsysuptime().setValue(new Counter32(time));

		if (SysPertriNetBean.getIfOnNet(oldstatus) != isOnnet) {
			VariableBinding[] vbs = new VariableBinding[10];
			vbs[0] = new VariableBinding(SgwMib.oidTrapVarNeid, new Counter32(Integer.valueOf(((SysParamBean) this.sysparamsMap.get("system.ne_type_id")).getValue()).intValue()));
			vbs[1] = new VariableBinding(SgwMib.oidTrapVarSgwid, new Counter32(1L));
			vbs[2] = new VariableBinding(SgwMib.oidTrapVarNename, new OctetString(((SysParamBean) this.sysparamsMap.get("system.sgw_server_name")).getValue()));
			vbs[3] = new VariableBinding(SgwMib.oidTrapVarDeployaddr, new OctetString(((SysParamBean) this.sysparamsMap.get("system.deployaddr")).getValue()));
			vbs[4] = new VariableBinding(SgwMib.oidTrapVarNEVendorName, new OctetString(((SysParamBean) this.sysparamsMap.get("system.vendor")).getValue()));
			vbs[5] = new VariableBinding(SgwMib.oidTrapVarNeversion, new OctetString(((SysParamBean) this.sysparamsMap.get("system.version")).getValue()));
			vbs[6] = new VariableBinding(SgwMib.oidTrapVarNodeId, new Counter32(Integer.valueOf(((SysParamBean) this.sysparamsMap.get("system.dr_id")).getValue()).intValue()));
			vbs[7] = new VariableBinding(SgwMib.oidTrapVarSgwbsnstate, new Counter32(isOnnet ? 0 : 1));
			vbs[8] = new VariableBinding(SgwMib.oidTrapVarSgwnestate, new Counter32(SysPertriNetBean.getSNMPStatusCode(newstatus)));
			vbs[9] = new VariableBinding(SgwMib.oidTrapVarSgwsysuptime, new Counter32(time));
			this.sgwMib.sGWStatesChanged(this.notificationOriginator, new OctetString(), vbs);
			logger.info("send SGWStatesChanged trap");
		}
	}

	public void notifyMsgError(int msgType, String reason, long time) {
		OID msgTypeOID = new OID(SgwMib.oidTrapVarMsgtype + ".0");
		OID resultOID = new OID(SgwMib.oidTrapVarMsgerrresult + ".0");
		OID updatetimeOID = new OID(SgwMib.oidTrapVarMsgupdatetime + ".0");

		VariableBinding[] vbs = new VariableBinding[3];
		vbs[0] = new VariableBinding(msgTypeOID, new Counter32(msgType));
		vbs[1] = new VariableBinding(resultOID, new OctetString(reason));
		vbs[2] = new VariableBinding(updatetimeOID, new Counter32(time));
		this.sgwMib.msgErrorNotify(this.notificationOriginator, null, vbs);
		logger.info("send msgErrorNotify trap");
	}

	public void notifyfileError(String reason, long time) {
		VariableBinding[] vbs = new VariableBinding[2];
		vbs[0] = new VariableBinding(SgwMib.oidTrapVarFileresult, new OctetString(reason));
		vbs[1] = new VariableBinding(SgwMib.oidTrapVarFileupdatetime, new Counter32(time));
		this.sgwMib.fileErrorNotify(this.notificationOriginator, null, vbs);
		logger.info("send fileErrorNotify trap");
	}

	public void notifyInterfaceConnectsCntMax(int maxConnect, long time) {
		VariableBinding[] vbs = new VariableBinding[2];
		vbs[0] = new VariableBinding(SgwMib.oidTrapVarMaxconnections, new Counter32(maxConnect));
		vbs[1] = new VariableBinding(SgwMib.oidTrapVarLinkalertupdatetime, new Counter32(time));
		this.sgwMib.interfaceConnectsCntMaxNotify(this.notificationOriginator, null, vbs);
		logger.info("send interfaceConnectsCntMaxNotify trap");
	}

	public void notifyFlowSizeAlert(String nodeCode, String userName, String capability, int count, long size, String reason, long time) {
		VariableBinding[] vbs = new VariableBinding[7];
		vbs[0] = new VariableBinding(new OID(SgwMib.oidTrapVarFlowalertnecode + ".0.0.0"), new OctetString(nodeCode));
		vbs[1] = new VariableBinding(new OID(SgwMib.oidTrapVarFlowalertuser + ".0.0.0"), new OctetString(userName));
		vbs[2] = new VariableBinding(new OID(SgwMib.oidTrapVarFLOWALERTCapability + ".0.0.0"), new OctetString(capability));
		vbs[3] = new VariableBinding(new OID(SgwMib.oidTrapVarFLOWALERTFLOWCount + ".0.0.0"), new Counter32(count));
		vbs[4] = new VariableBinding(new OID(SgwMib.oidTrapVarFlowalertflowszie + ".0.0.0"), new Counter32(size));
		vbs[5] = new VariableBinding(new OID(SgwMib.oidTrapVarAlertreason + ".0.0.0"), new OctetString(reason));
		vbs[6] = new VariableBinding(new OID(SgwMib.oidTrapVarFlowalertupdatetime + ".0.0.0"), new Counter32(time));
		this.sgwMib.flowSizeAlertNotify(this.notificationOriginator, null, vbs);
		logger.info("send flowSizeAlertNotify trap");
	}

	public void notifyBlockChanged(int oldlevel, int newlevel, long time) {
		VariableBinding[] vbs = new VariableBinding[3];
		vbs[0] = new VariableBinding(SgwMib.oidTrapVarOldlevel, new Counter32(oldlevel));
		vbs[1] = new VariableBinding(SgwMib.oidTrapVarNewlevel, new Counter32(newlevel));
		vbs[2] = new VariableBinding(SgwMib.oidTrapVarLevelupdatetime, new Counter32(time));
		this.sgwMib.getSgwconlevel().setValue(new Counter32(newlevel));
		this.sgwMib.blockChangedNotify(this.notificationOriginator, null, vbs);
		logger.info("send blockChangedNotify trap");
	}

	public void notifyInterfaceRunningError(String nodeCode, int linkState, String linkStateDesc, long time) {
		VariableBinding[] vbs = new VariableBinding[4];
		vbs[0] = new VariableBinding(new OID(SgwMib.oidTrapVarLinknecode + ".0"), new OctetString(nodeCode));
		vbs[1] = new VariableBinding(new OID(SgwMib.oidTrapVarLinkstate + ".0"), new Counter32(linkState));
		vbs[2] = new VariableBinding(new OID(SgwMib.oidTrapVarLinkstatedesc + ".0"), new OctetString(linkStateDesc));
		vbs[3] = new VariableBinding(new OID(SgwMib.oidTrapVarLinkupdatetime + ".0"), new Counter32(time));
		this.sgwMib.interfaceRunningErrorNotify(this.notificationOriginator, null, vbs);
		logger.info("send interfaceRunningErrorNotify trap");
	}

	public void setSgwMib(SgwMib sgwMib) {
		this.sgwMib = sgwMib;
	}

	public void setNotificationOriginator(NotificationOriginator notificationOriginator) {
		this.notificationOriginator = notificationOriginator;
	}

	public void setConfigFile(String configFile) {
		this.configFile = configFile;
	}

	@Autowired
	public void setNodeDataFetcher(NodeDataFetcher nodeDataFetcher) {
		this.nodeDataFetcher = nodeDataFetcher;
	}
}